home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / x25 / nrs.shar.Z / nrs.shar / lru.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-27  |  4.0 KB  |  172 lines

  1. # include    "nrs.h"
  2.  
  3. # ifndef lint
  4. static char RCSid[]="@(#)$Header: lru.c,v 3.1 86/10/15 08:13:18 pb Rel $";
  5. # endif
  6.  
  7. /***********************************************************************\
  8. *                                     *
  9. * get a file descriptor. As there are up to 39+ files in use, these    *
  10. * are kept in an lru queue to keep i/o efficient.            *
  11. * These routines are based heavily on those Dave Allsopp wrote        *
  12. * for a compiler, Thanks Dave.                        *
  13. *                                     *
  14. * Copyright 1986, Piete Brooks, Julian Onions & Adrian Pell        *
  15. * pb@cl.cam.ac.uk, jpo@hcig.nott.ac.uk, Adrian.R.Pell@reading.ac.uk    *
  16. *                                    *
  17. * This program may be copied as long as you don't remove this notice,    *
  18. * try to make any money off of it, or pretend that you wrote it.    *
  19. *                                     *
  20. \***********************************************************************/
  21.  
  22. # define    NILLIST        ((Flist *)0)
  23. # define    MAXOPENFILES    10    /* max files kept in lru queue */
  24. # define    MAXFILES    64    /* max files kept in table */
  25.  
  26. typedef    struct flist { /* the lru queue unit */
  27.     FILE    *fp;
  28.     int    tab_no;
  29.     struct    flist *next;
  30. } Flist;
  31.  
  32. typedef struct Files {
  33.     char    *filename;
  34.     int    used;
  35. } Files;
  36.  
  37. static    Files    FileList[MAXFILES];
  38. static    Flist    *Head = NILLIST;    /* the head of the lru list */
  39. static_f Flist    *search_list();
  40. static_f int    getfileindex();
  41. static_f void    tohead();
  42. static_f Flist    *get_newfl();
  43.  
  44. FILE    *getfp(name, mode)    /* find fp for name opening if necessary */
  45. char    *name;
  46. char    *mode;
  47. {
  48.     Flist    *flp;
  49.     int    n;
  50.     
  51.     n = getfileindex(name);
  52.     if((flp = search_list(n, Head)) == NILLIST)
  53.         flp = get_newfl(n, &Head, mode);
  54.  
  55.     if (flp == NILLIST) return (FILE *) 0;
  56.  
  57.     tohead(n, &Head);    /* shift to head of queue */
  58.     return flp->fp;
  59. }
  60.  
  61. static_f
  62. Flist *
  63. search_list(n, start)
  64. int    n;
  65. Flist    *start;
  66. {
  67.     register Flist    **tracer;
  68.  
  69.     for(tracer = &start; *tracer != NILLIST && (*tracer)->tab_no != n;
  70.             tracer = &(*tracer)->next)
  71.             ;
  72.     return    *tracer;
  73. }
  74.  
  75. static_f Flist    *get_newfl(n, start, mode)    /* open the file */
  76. int    n;
  77. Flist    **start;
  78. char    *mode;
  79. {
  80.     register Flist    **tracer = start;
  81.     register int    i;
  82.     char    newmode[4];
  83.     int    soft_fail = *mode == 'S';
  84.  
  85.     if (soft_fail) mode++;
  86.  
  87. #ifdef PRIME
  88.     if (*mode == 'r')
  89.         VOID strcpy(newmode, "i");
  90.     else if (*mode == 'w' && FileList[n].used)  /* convert to an append */
  91.         VOID strcpy(newmode, "oa+");
  92.     else
  93.         VOID strcpy(newmode, "o+");
  94. #else  PRIME
  95.     if( *mode == 'w' && FileList[n].used)    /* convert to an append */
  96.         newmode[0] = 'a';
  97.     else    newmode[0] = *mode;
  98.     newmode[1] = mode[1];
  99.     newmode[2] = '\0';
  100. #endif PRIME
  101.  
  102.     if( *tracer == NILLIST)    /* nothing in the queue, make an entry */
  103.     {
  104.         *tracer = (Flist *)malloc((unsigned) sizeof(Flist));
  105.         if( *tracer == NILLIST)
  106.             fatal0("Out of memory in lru");
  107.         (*tracer)->next = NILLIST;
  108.     }
  109.     else
  110.     {
  111.         for( i = 1; (*tracer)->next != NILLIST; i++)
  112.             tracer = &(*tracer)->next;
  113.         if( i == MAXOPENFILES) /* time to shut one down */
  114.             VOID fclose((*tracer)->fp);
  115.         else /* room for a small one ? */
  116.         {
  117.             tracer = &(*tracer)->next;
  118.             *tracer = (Flist *)malloc((unsigned) sizeof(Flist));
  119.             if( *tracer == NILLIST)
  120.                 fatal0("Out of memory");
  121.             (*tracer)->next = NILLIST;
  122.          }
  123.     }
  124.     if(((*tracer)->fp = fopen(FileList[n].filename, newmode)) == NULL)
  125.     {    if (soft_fail)
  126.         {    Flist *next = (*tracer)->next;
  127.             free((char *) (*tracer));
  128.             *tracer = next;
  129.             return NILLIST;
  130.         }
  131.         fatal1("Can't open file %s", FileList[n].filename);
  132.     }
  133.     FileList[n].used = 1;
  134.     (*tracer)->tab_no = n;
  135.     return *tracer;
  136. }
  137.  
  138. static_f void
  139. tohead(n, start)    /* move node n to head of list */
  140. int    n;
  141. Flist    **start;
  142. {
  143.     register Flist **tracer = start;
  144.     register Flist    *tmp;
  145.  
  146.     while(*tracer != NILLIST && (*tracer)->tab_no != n)
  147.         tracer = &(*tracer)->next;
  148.     if( *tracer == NILLIST)
  149.         fatal1("lru botch looking for %d", n);
  150.     tmp = *tracer;
  151.     *tracer = tmp->next;
  152.     tmp->next = *start;
  153.     *start = tmp;
  154. }
  155.  
  156. static_f int
  157. getfileindex(name)
  158. char    *name;
  159. {
  160.     Files    *fsp;
  161.  
  162.     for(fsp = FileList; fsp->filename != NULL; fsp++)
  163.         if( strcmp(fsp->filename, name) == 0)
  164.             return fsp - FileList;
  165. /* make a new entry */
  166.     if( fsp - FileList > MAXFILES )
  167.         fatal0("Too many files to deal with - help");
  168.     fsp->filename = strdup(name);
  169.     fsp->used = 0;
  170.     return fsp - FileList;
  171. }
  172.